package Mojolicious::Command::generate::actions;
use Mojo::Base 'Mojo::Command';
use Mojo::Util qw/camelize decamelize/;
use Data::Dumper;

has description => <<'EOF';
Generate controllers files with actions with in.
EOF
has usage => <<"EOF"; 
usage: $0 generate actions [csv|dump]
EOF

sub run {
    my $self       = shift;
    my $out_format = shift || '';
    my %all_form   = ( dump => \&Dumper, csv => \&_csv );
    die "Allowed formats: " . join( ',', map { "'$_'" } keys(%all_form) )
      if $out_format and !$all_form{$out_format};

    # Check if application has routes
    my $app = $self->app;
    die "Application has no routes.\n" unless $app->can('routes');

    # Walk
    my ( @result, $curr_namespace ) = ( (), '' );
    $self->_walk( $app->routes, \@result, \$curr_namespace );

    if ( $all_form{$out_format} ) {
        print &{ $all_form{$out_format} }( \@result );
    }
    else {
        #generate
        $self->_generate( \@result );
    }
}

sub _walk {
    my $se = shift;
    my $n  = shift;    # node
    my ( $result, $curr_namespace ) = @_;

    $$curr_namespace = $n->namespace if $n->namespace;
    my $p  = $n->pattern;
    my $pa = $p->pattern || '';
    my $co = $p->defaults->{controller} || '';
    camelize($co);
    my $ac = $p->defaults->{action} || '';
    #Class path with full filename:
    my $cp = $se->class_to_path( join( '::', 'lib', $$curr_namespace, $co ) ) if $co;
    $cp ||= '';
    #Package name:
    my $pkg = join( '::', $$curr_namespace, $co );
    $pkg ||= 'Unknown-controller(fix me)';
    #Templates path:
    my $tp = join( '/', 'templates', decamelize($co), $ac ).'.html.ep' if $co;
    $tp ||= '';
    # Placeholders in pattern
    my @pl_holds = $pa =~/\:(\w+)/g;
    my %pl_holds = map { $_, qr/\w+/ } @pl_holds;
    # Parameters into 'sub' body
    my %pars = ( %pl_holds, %{ $p->reqs }, %{ $p->defaults }  );
    # We'll not write 'controller' and 'action' into sub body 
    delete @pars{qw/controller action/};

    #Each route description (as a hash_ref) push into array
    push @$result,
      {
        pattern    => $pa,
        controller => $co,
        action     => $ac,
        class_path => $cp,
        templates_path => $tp,
        pars       => \%pars,
        pkg        => $pkg,
        cn         => $$curr_namespace,
        name       => $n->name,
      };
    # This is recursive function
    $se->_walk( $_, $result, $curr_namespace ) for @{ $n->children };
}

sub _csv {
    # Print all routes descriptions as a csv text into stdout.
    my $r = shift;
    for my $ro (@$r) {
        next if !ref $ro;
        my %ro   = %$ro;
        my %pars = %{ $ro{pars} || {} };
        my $pars = join ',', map { "$_=$pars{$_}" } keys %pars;
        next if !@ro{qw/ pattern controller  /} and !$pars;
        say join( ';', @ro{qw/ pattern controller action class_path templates_path/}, $pars );
    }
}

sub _generate {
    # Generate controllers with actions and templates.
    my $self = shift;
    my $r    = shift;
    # I remember, what many routes may refer to one file.
    my %rou;
    for my $ro (@$r) {
        next if !ref $ro;
        next if !$ro->{class_path};

        #die Dumper $ro if $ro->{class_path};
        push @{ $rou{ $ro->{class_path} } },  $ro;

    }
    for my $class_path ( keys %rou ){
	my $routes_aref = $rou{ $class_path }||[];
        if ( -e $class_path ){
    	    say "Exist $class_path. Skip."
        }
        else{
	    $self->render_to_rel_file( 'controller', $class_path || '', $routes_aref );

        }
        for my $route ( @$routes_aref ){
    	    my $template_path = $route->{templates_path} or die 'path!';
    	    if ( -e $template_path ){
    		say "Exist $template_path. Skip."
    	    }
    	    else{    
		$self->render_to_rel_file( 'template',  $template_path || '', $route );
    	    }
        }
    }
    
    
}

1;

__DATA__

@@ controller
% my $routes = shift;
% my $pkg = $routes->[0]->{pkg};

package <%= $pkg||'fix_me' %>;
use Mojo::Base 'Mojolicious::Controller';
use Data::Dumper;

% for my $r ( @$routes ){ 
% my %route = %$r; 
% my %pars_to_action = %{$route{pars}};
sub <%= $route{action}||'fix_me' %> {
  my $self = shift;
  % for my $pn ( sort keys %pars_to_action ){
  my $<%=$pn%> = $self->stash("<%= $pn %>");
  % }
  # my $r_name = "<%=$r->{name}%>"; 
  # die "Called ".$self->stash('controller')."#".$self->stash('action');
  
}
% } 

1;

@@ template
% my $route = shift||{};
<%%= stylesheet '/1.css'; %>
This is template <%= $route->{name}; %>
<br>Parameters: <%= join ';', map {"$_= \<\%\= stash '$_' \%\><br>"} keys %{$route->{pars}}  %>


